# 导入必要的库  
from bs4 import BeautifulSoup  # 用于解析HTML文档  
from bs4.dammit import UnicodeDammit  # 用于处理字符编码问题  
import requests  # 用于发送HTTP请求  
import pandas as pd  # 用于数据处理和生成DataFrame  
  
# 目标URL，即我们要抓取的当当网搜索页面地址（已进行URL编码）  
url = "http://search.dangdang.com/?key=%CA%E9%B0%FC&act=input"  
  
try:  
    # 设置HTTP请求头，模拟浏览器访问，避免被网站反爬虫机制识别为爬虫  
    headers = {  
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"  
    }  
  
    # 发送HTTP GET请求到目标URL，并带上请求头  
    data = requests.get(url, headers=headers)  
  
    # 检查请求是否成功，如果失败则抛出HTTPError异常  
    data.raise_for_status()  
  
    # 获取网页的原始内容（字节码）  
    raw_content = data.content  
  
    # 使用UnicodeDammit处理字符编码问题，尝试使用utf-8和gbk编码，选择最合适的编码方式  
    dammit = UnicodeDammit(raw_content, ["utf-8", "gbk"])  
  
    # 获取处理后的Unicode字符串（即HTML文档）  
    html_content = dammit.unicode_markup  
  
    # 使用BeautifulSoup解析HTML文档，'lxml'是解析器  
    soup = BeautifulSoup(html_content, "lxml")  
  
    # 使用CSS选择器查找所有匹配的<li>元素，这些元素位于class为'bigimg'的<ul>下  
    # 注意：这里的选择器需要根据网页的实际结构进行调整  
    lis = soup.select("ul.bigimg li")  
  
    # 初始化一个空列表，用于存储每个商品的数据  
    products_data = []  
  
    # 遍历每个<li>元素（即每个商品）  
    for li in lis:  
        try:  
            # 初始化一个空列表，用于存储当前商品的数据  
            current_product_data = []  
  
            # 使用CSS选择器查找商品名称的<a>标签，并获取其title属性（商品名称）  
            # 注意：如果<a>标签不存在或没有title属性，将返回空字符串  
            name_tag = li.select_one("p.name a")  
            name = name_tag.get('title', '') if name_tag else ''  
  
            # 使用CSS选择器查找商品价格，并获取其文本内容（去除前后空白）  
            # 注意：如果价格标签不存在，将返回空字符串  
            price_tag = li.select_one("span.price_n")  
            price = price_tag.text.strip() if price_tag else ''  
  
            # 将商品名称和价格添加到当前商品的数据列表中  
            current_product_data.append(name)  
            current_product_data.append(price)  
  
            # 将当前商品的数据列表添加到总列表中  
            products_data.append(current_product_data)  
        except Exception as err:  
            # 如果在处理某个商品时发生异常，则打印错误信息，并继续处理下一个商品  
            print(f"Error processing item: {err}")  
  
    # 使用pandas库将总列表转换为DataFrame，并指定列名  
    df = pd.DataFrame(products_data, columns=['商品名称', '价格'])  
  
    # 调整DataFrame中列的顺序，将'价格'列放在前面，'商品名称'列放在后面  
    df = df[['价格', '商品名称']]  
  
    # 打印DataFrame，查看抓取到的商品数据  
    print(df)  
except Exception as err:  
    # 如果在请求网页或处理数据时发生异常，则打印错误信息  
    print(f"An error occurred: {err}")